#include "config.h"
#include "md_adapter.h"
#include "sms_basic_types.h"
#include "sms_router.h"

#include <glib.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/socket.h>
#include <sys/errno.h>

#define LISTEN_QUEUE 1024
#define NET_BUF_LEN 1024
#define LISTEN_QUEUE 1024
#define NET_BUF_LEN 1024

#define SERVER_PORT 8081
#define CONFIGURE_FILE_NAME "sms_router.conf"


int tcp_server_init()
{
    int serv_sockfd, flag, ret;
    struct sockaddr_in server_addr;

    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htons(INADDR_ANY);
    server_addr.sin_port = htons(SERVER_PORT);

    if ((serv_sockfd = socket(AF_INET,SOCK_STREAM,0))<0)
    {
        printf("Creat socket failed !\n");
        exit(1);
    } 
    // send or receive packet no delay
    ret = setsockopt(serv_sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag) );

    if (ret == -1) 
    {
        printf("Couldn't setsockopt(TCP_NODELAY)\n");
        exit( EXIT_FAILURE );
    }
    if ((bind(serv_sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr)))<0)
    {
        printf("bind port %d failed !\n",SERVER_PORT);
        exit(1);
    }
    if ((listen(serv_sockfd,LISTEN_QUEUE))<0)
    {
        printf("server listen failed !\r\n "); 
        exit(1); 

    }

    return serv_sockfd;
}


GArray *create_senders()
{
    int group_count;
    GPtrArray *array;
    gchar **groups;
    GKeyFile *keyfile;
    GKeyFileFlags flags;
    GError *error = NULL;
    gsize length;

    keyfile = g_key_file_new ();
    flags = G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS;

    if (!g_key_file_load_from_file (keyfile, CONFIGURE_FILE_NAME, flags, &error))
    {
        g_error(error->message);
        g_key_file_free(keyfile);
        return NULL;
    }
    groups = g_key_file_get_groups(keyfile, NULL);
    array = g_ptr_array_new();
    if (groups == NULL)
    {
        printf("there should be one sender at least!!\n");
        g_key_file_free(keyfile);
        return NULL;
    }
    group_count = g_strv_length(groups);
    int i = 0;
    for (i; i < group_count; i++)
    {
        SENDER_PARAMETER *sender;
        if((!g_key_file_has_key(keyfile, groups[i], "sn", &error)) 
            || (!g_key_file_has_key(keyfile, groups[i], "password", &error))
            || (!g_key_file_has_key(keyfile, groups[i], "filter", &error))
            || (!g_key_file_has_key(keyfile, groups[i], "name", &error)))
        {
            g_key_file_free(keyfile);
            g_strfreev(groups);
            g_ptr_array_free(array, TRUE);
            return NULL;
        }  

        sender = sender_para_init();
        
        if (sender == NULL)
        {
            return NULL;
        }

        g_stpcpy(sender->name, g_key_file_get_string(keyfile, groups[i], "name", NULL));
        g_stpcpy(sender->sn, g_key_file_get_string(keyfile, groups[i], "sn", NULL));
        g_stpcpy(sender->password, g_key_file_get_string(keyfile, groups[i], "password", NULL));
        g_stpcpy(sender->filter_string, g_key_file_get_string(keyfile, groups[i], "filter", NULL));
        sender->filter = g_regex_new(sender->filter_string, 0, 0, &error);
        if (sender->filter == NULL)
        {
            g_error(error->message);
            g_key_file_free(keyfile);
            g_strfreev(groups);
            g_ptr_array_free(array, TRUE);
            return NULL;
        }
        if (strcmp(sender->name, "mdapi"))
        {
            sender->status = md_check_service_status;
            sender->send_message = md_send_message;
            sender->send_grouped_messages = md_send_message;
            sender->send_grouped_individual_messages = md_send_individual_messages;   
        }
        fprintf(stderr, "read sender name %s, sn %s, password %s\n", 
                sender->name, sender->sn, sender->password);      
        g_ptr_array_add(array, sender);
    }
    g_key_file_free(keyfile);
    g_strfreev(groups);
    return array;
}


int main()
{
    int sockfd,cli_sockfd;
    struct sockaddr_in client_addr;
    socklen_t length;
    pthread_t recv_thread_id, send_thread_id;
    // sender will release in the send_thread.
    GPtrArray *senders = NULL;
    // INIT
    debug_open_log(); 
    sockfd = tcp_server_init();
    // crate sender thread.
    senders = create_senders();
    if (senders == NULL)
    {
        printf("create sender parameter error!");
        exit(0);
    }
    int i = 0;
    for (i; i < senders->len; i ++)
    {
        SENDER_PARAMETER *sender = g_ptr_array_index(senders, i);
        pthread_create(&send_thread_id, NULL, send_thread, sender);
    }
    while (1)
    {
        length = sizeof(client_addr);
        printf("start accept \n");
        if ((cli_sockfd = accept(sockfd,(struct sockaddr *)&client_addr,&length))<0)
        {
            printf("tcp server accept error! \n");
            break;
        }
        // this recv_param will be dealloced in thread.
        RECEIVER_PARAMETER *recv_param = g_new0(RECEIVER_PARAMETER, 1);
        recv_param->cli_sockfd = cli_sockfd;
        recv_param->senders = senders;
        // init thread parameters
        if(pthread_create(&recv_thread_id, NULL, recv_thread, (void*)recv_param)<0)
        {
            printf("tcp server create thread error:%s !\n", strerror(errno));
        }
        else
        {
            printf("create thread : thread_id -> %d  ok !\n", recv_thread_id);
        }

    }
    g_ptr_array_free(senders, FALSE);
    close(cli_sockfd);
    close(sockfd);
    pthread_exit(NULL);
    return 0;
}
